#include "HotSpotManager.hpp"

#define MSG_GO_THROUGH "go through"
#define MSG_DOOR_LOCKED "door is locked"
#define MSG_DOOR_OPENED "door opened"

#define MSG_OPEN "open"
#define MSG_CHEST_LOCKED "chest is locked"
#define MSG_CHEST_OPENED "chest opened"

#define MSG_ACTIVATE "activate"
#define MSG_LEVER_BLOCKED "lever blocked"

namespace backpack {



HotSpotVariant UnlockPointBuilder::buildImpl() const {
  assert (Key::c_null != m_refKey.get());
  assert (g_actionNull != m_action);

  UnlockPoint* unlockpoint = new UnlockPoint(
      m_strName,
      m_strDescription,
      m_strChoice,
      m_strLocation,
      m_strLocked,
      m_action,
      m_refKey.get()
      );
  unlockpoint->setEnabled(m_bEnabled);
  unlockpoint->setVisible(m_bVisible);
  unlockpoint->setChildHotSpot(m_hotSpotChild);
  return *unlockpoint;
}



HotSpotVariant WayPointBuilder::buildImpl() const {
  assert ("" != m_strLocked);

  WayPoint* waypoint = new WayPoint(
      m_strName,
      m_strDescription,
      m_strChoice,
      m_strLocation,
      m_strLocked,
      m_refNodeTarget
      );
  waypoint->setEnabled(m_bEnabled);
  waypoint->setVisible(m_bVisible);
  waypoint->setChildHotSpot(m_hotSpotChild);

  if (nullptr != m_ptrUnlockPointBuilder) {
    assert (g_hotSpotNull == m_hotSpotChild);

    waypoint->setChildHotSpot(m_ptrUnlockPointBuilder->withAction(
          EnableAction(MSG_DOOR_OPENED, "", *waypoint)));
  }

  return *waypoint;
}



HotSpotVariant ItemPointBuilder::buildImpl() const {
  assert ("" != m_strLocked);

  MultiAction actions;
  TouchPoint* touchpoint = new TouchPoint(
      m_strName,
      m_strDescription,
      m_strChoice,
      m_strLocation,
      m_strLocked,
      actions
      );
  touchpoint->setEnabled(m_bEnabled);
  touchpoint->setVisible(m_bVisible);
  touchpoint->setChildHotSpot(m_hotSpotChild);

  std::for_each(
      m_listItems.begin(),
      m_listItems.end(),
      [&actions] (ItemVariant const& item) {
        actions.add(AddItemAction(item));
      });
  actions.add(HideAction("", "", *touchpoint));

  if (nullptr != m_ptrUnlockPointBuilder) {
    assert (g_hotSpotNull == m_hotSpotChild);

    touchpoint->setChildHotSpot(m_ptrUnlockPointBuilder->withAction(
          EnableAction(MSG_CHEST_OPENED, "", *touchpoint)));
  }

  return *touchpoint;
}




HotSpotVariant LeverPointBuilder::buildImpl() const {
  assert ("" != m_strLocked);
  assert (m_listActions.size() > 0);

  MultiAction actions;
  TouchPoint* touchpoint = new TouchPoint(
      m_strName,
      m_strDescription,
      m_strChoice,
      m_strLocation,
      m_strLocked,
      actions
      );
  touchpoint->setEnabled(m_bEnabled);
  touchpoint->setVisible(m_bVisible);
  touchpoint->setChildHotSpot(m_hotSpotChild);

  std::for_each(
      m_listActions.begin(),
      m_listActions.end(),
      [=] (ActionVariant const& action) {
        MultiAction(actions).add(action);
      });
  if (m_bOneShot) {
    actions.add(HideAction("", "", *touchpoint));
  }

  return *touchpoint;
}




HotSpotManager::~HotSpotManager() {
  auto visitor = makeHotSpotVisitor(m_deleter);
  std::for_each(
      m_listStorage.begin(),
      m_listStorage.end(),
      boost::apply_visitor(visitor)
      );
}


WayPointBuilder HotSpotManager::newDoor(std::string const& name) {
  return WayPointBuilder(m_listStorage, name)
    .withChoice(MSG_GO_THROUGH)
    .withLockedMessage(MSG_DOOR_LOCKED);
}


UnlockPointBuilder HotSpotManager::newKeyHole(Key &key) {
  return UnlockPointBuilder(m_listStorage, key.getName() + "key hole")
    .unlockedWithKey(key)
    .enabled();
}


ItemPointBuilder HotSpotManager::newChest(std::string const& name) {
  return ItemPointBuilder(m_listStorage, name)
    .withChoice(MSG_OPEN)
    .withLockedMessage(MSG_CHEST_LOCKED);
}


LeverPointBuilder HotSpotManager::newLever(std::string const& name) {
  return LeverPointBuilder(m_listStorage, name)
    .withChoice(MSG_ACTIVATE)
    .withLockedMessage(MSG_LEVER_BLOCKED)
    .enabled();
}



} // namespace backpack

